<?php
/**
 * Map implementation based on an array.
 *
 * @package be.appcraft.util
 * @version $Revision: 1.1 $
 *
 * @author Stijn Van Bael
 * @since 1.0
 */
class Pageley_Util_ArrayMap implements Pageley_Util_Map {

	/**
	 * The array containing the key/value pairs.
	 */
	private $entries;

	
	/**
	 * Constructs a new ArrayMap.
	 *
	 * @param array $entries: an array to create the map from or null to create
	 * a new array
	 */
	public function __construct() {
        if(func_num_args() > 0) {
            $arg0 = func_get_arg(0);
            if(is_array($arg0)) {
                $this->entries = $arg0;
            } else {
                $this->entries = func_get_args();
            }
        } else {
            $this->entries = array();
        }
	}

	/**
	 * {@inheritdoc}
	 */
	public function get($key) {
		return $this->containsKey($key) ? $this->entries[$key] : null;
	}

	/**
	 * {@inheritdoc}
	 */
	public function add($value) {
		array_push($this->entries, $value);
		return $this;
	}

	public function addAll($collection) {
		foreach($collection as $entry) {
			$this->add($entry);
		}
	}

	public function putAll($map) {
		foreach($map as $key => $value) {
			$this->put($key, $value);
		}
	}

	/**
	 * {@inheritdoc}
	 */
	public function put($key, $value) {
		$this->entries[$key] = $value;
		return $this;
	}

	public function prepend($key, $value) {
		$this->entries = array($key => $value) + $this->entries;
	}

	/**
	 * {@inheritdoc}
	 */
	public function size() {
		return count($this->entries);
	}

	/**
	 * {@inheritdoc}
	 */
	public function toArray() {
		return $this->entries;
	}

	/**
	 * {@inheritdoc}
	 */
	public function containsKey($key) {
		return array_key_exists($key, $this->entries);
	}

	/**
	 * {@inheritdoc}
	 */
	public function containsValue($value) {
		return in_array($value, $this->entries);
	}

	/**
	 * {@inheritdoc}
	 */
	public function getIterator() {
		return new ArrayIterator($this->entries);
	}

	/**
	 * {@inheritdoc}
	 */
	public function remove($key) {
		unset($this->entries[$key]);
		return $this;
	}

	/**
	 * {@inheritdoc}
	 */
	public function removeValue($value) {
		$key = null;
		reset($this->entries);
		while ($currentValue = current($this->entries)) {
		    if ($currentValue === $value) {
		        $key = key($this->entries);
		    }
		    next($this->entries);
		}
		if($key !== null) {
			$this->remove($key);
		}
		return $this;
	}

	/**
	 * {@inheritdoc}
	 */
	public function isEmpty() {
		return $this->size() == 0;
	}

	public function sortByKey() {
		ksort($this->entries);
	}

	public function sortByValue() {
		asort($this->entries);
	}

	public function reverse() {
		$this->entries = array_reverse($this->entries, true);
	}

	public function __clone() {
		$newEntries = array();
		foreach($this->entries as $key => $value) {
			$newEntries[$key] = $value;
		}
		return new Pageley_Util_ArrayMap($newEntries);
	}

	public function __toString() {
		$string = null;
	    try {
            $string = "[ ";
    		$first = true;
    		foreach($this->entries as $key => $value) {
    			if($first) {
    				$first = false;
    			} else {
    				$string .= ", ";
    			}
    			$string .= "(" . $key . ") => (" .$value . ")";
    		}
    		$string .= " ]";
        } catch(Exception $e) {
            $string = $e->getMessage();
        }
		return $string;
	}

	public function equals($arrayMap) {
		if($arrayMap === null) {
			return false;
		}
		if(!($arrayMap instanceof Pageley_Util_ArrayMap)) {
			return false;
		}
		$equal = true;
		foreach($this->entries as $key => $localValue) {
			$remoteValue = $arrayMap->get($key);
			if(!Pageley_Util_Equals::isEqual($localValue, $remoteValue)) {
				$equal = false;
				break;
			}
		}
		return $equal;
	}

	public function push($value) {
		array_push($this->entries, $value);
	}

    public function shift() {
        return array_shift($this->entries);
    }
    
    public function sort($comparator = null) {
    	if($comparator === null) {
    		$comparator = new Pageley_Util_NaturalComparator();
    	}
    	usort($this->entries, array($comparator, "compare"));
    }
    
    public function clear() {
        $this->entries = array();
    }
    
    public function keys() {
        $keys = new Pageley_Util_ArrayMap();
        foreach($this->entries as $key => $entry) {
            $keys->add($key);
        }
        return $keys;
    }
}